package com.cneport.das.client.trans.receive;

import com.cneport.das.client.conf.ClientConfCache;
import com.cneport.das.client.conf.FileConf;
import com.cneport.das.client.conf.TransConf;
import com.cneport.das.client.trans.service.TransClientService;
import com.cneport.das.common.model.trans.ClientGetResponse;
import com.cneport.das.common.utils.BizRecorder;
import com.cneport.das.common.utils.JAXBUtils;
import com.cneport.das.common.utils.RandomGenerator;
import com.cneport.das.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @Desc 收取消息并写入文件系统
 * @Ver 1.0
 * @Author GavinZhang
 * @Company 东方物通科技有限（北京）公司
 * @Date 2021-12-21 10:02:23
 */
@Slf4j
@Component
public class ReceiveBySchedule {
    @Autowired
    private TransClientService transClientService;
    @Autowired
    private ClientConfCache clientConfCache;
    @Autowired
    private BizRecorder recorder;

    private static final Long minutes2Mills = 1000L;


    /**
     * 用来记录下次触发时间
     */
    private static final Map<String, Long> nextTrigger = new ConcurrentHashMap();

    /**
     * 每分钟触发一次，逐个多线程收
     */
    @Scheduled(initialDelay = 1000L, fixedRate = 60 * 1000L)
    public void receive() {
        ExecutorService pool = new ThreadPoolExecutor(2, 3, 5, TimeUnit.MINUTES, new LinkedBlockingQueue<>());
        Set<String> corpNos = clientConfCache.getAllCorpNo();
        if (corpNos != null) {
            for (String corpNo : corpNos) {
                TransConf corp = clientConfCache.getTransConfigByCorpNo(corpNo);
                FileConf fileConf = clientConfCache.getFileConfigByCorpNo(corpNo);
                if (corp == null || fileConf == null) {
                    continue;
                }
                ReceiveTask task = new ReceiveTask(corp, fileConf, corp.getLicence(), corp.getEncoderVer());
                FileConf.FileDown fileDown = fileConf.getFileDown();
                if (fileDown == null) {
                    continue;
                }
                Long fre = fileDown.getFreq();
                if (fre == null) {
                    fre = 3L;
                }
                if (nextTrigger.get(corpNo) == null || nextTrigger.get(corpNo) <= System.currentTimeMillis()) {
                    pool.submit(task);
                    nextTrigger.put(corpNo, System.currentTimeMillis() + fre * minutes2Mills);
                }

            }

        }
        pool.shutdown();
    }

    private class ReceiveTask implements Runnable {

        TransConf dc;
        FileConf fc;
        String encoderVer;
        String corpLic;

        public ReceiveTask(TransConf dc, FileConf fc, String copLic, String encoderVer) {
            this.dc = dc;
            this.fc = fc;
            this.encoderVer = encoderVer;
            this.corpLic = copLic;
        }

        @Override
        public void run() {
            String guid = RandomGenerator.genGuid();
            log.info("本次查询开始guid：" + guid + ",corpNo:" + dc.getCorpNo());
            String msg = transClientService.getMsgBySchedule(guid, dc.getCorpNo(), corpLic, fc.getFileDown().getMaxCnt(), encoderVer);
            if (StringUtil.isBlank(msg)) {
                log.info("本次查询结束,guid：" + guid + " 没有信息！ ");
                return;
            }
            ClientGetResponse response = JAXBUtils.xml2Obj(ClientGetResponse.class, msg);
            String respCode = response.getRespHead().getRespCode();
            if ("0".equals(respCode)) {
                List<String> ls = response.getRespData().getData();
                //写文件
                if (ls == null || ls.size() == 0) {
                    log.info("本次查询结束,guid：" + guid + " 没有信息！ ");
                    return;
                } else {

                    recorder.receiveXml(fc.getFileDown().getOut(), null, guid, "xml", ls);
                    log.info("本次查询完成guid：" + guid + " !");
                }

            } else {
                log.error("查询失败！" + response.getRespHead().getRespMsg());
            }
        }
    }

    /**
     * 解析XML 根标签
     *
     * @param xml
     * @return 业务类型代码
     */
    private static String parseBizType(String xml) {
        xml = xml.replace("\n", "");
        xml = xml.replace("\t", "");
        int indx = xml.indexOf("?>");

        int startTagPos = -1;
        int endTagPos = -1;
        if (indx == -1) {
            //无头 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
            //0开始，到第一个'>'
            for (int i = 0; i < xml.length(); i++) {
                char c = xml.charAt(i);
                if (c == '>') {
                    endTagPos = i;
                    startTagPos = 1;
                    break;
                }
            }

        } else {
            //从indx+2,到 第一个'>'
            for (int i = indx + 2; i < xml.length(); i++) {
                char c = xml.charAt(i);
                if (c == '>') {
                    endTagPos = i;
                    startTagPos = indx + 3;
                    break;
                }
            }
        }
        //不是xml
        if (endTagPos == -1) {
            return "";
        } else {
            return xml.substring(startTagPos, endTagPos);
        }

    }
}